package com.mkx.aqs;

import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;

/**
 * AQS队列的节点类
 * 表示AQS同步队列和条件队列中的一个节点，存储线程和等待状态等信息
 */
public class Node {
    // 节点模式常量
    /** 共享模式标记 */
    public static final Node SHARED = new Node();
    /** 独占模式标记 */
    public static final Node EXCLUSIVE = new Node();
    
    // 节点等待状态常量
    /** 表示节点已被取消（超时或中断） */
    public static final int CANCELLED =  1;
    /** 表示节点的后继节点需要被唤醒 */
    public static final int SIGNAL    = -1;
    /** 表示节点在条件队列中等待 */
    public static final int CONDITION = -2;
    /** 表示下一次共享模式获取操作应该无条件传播 */
    public static final int PROPAGATE = -3;
    
    // 节点的等待状态
    volatile int waitStatus;
    
    // 使用AtomicIntegerFieldUpdater进行waitStatus的原子更新
    private static final AtomicIntegerFieldUpdater<Node> WAIT_STATUS_UPDATER =  
            AtomicIntegerFieldUpdater.newUpdater(Node.class, "waitStatus");
    
    // 使用AtomicReferenceFieldUpdater进行next的原子更新
    private static final AtomicReferenceFieldUpdater<Node, Node> NEXT_UPDATER = 
            AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "next");
    
    // 前驱节点引用
    volatile Node prev;
    
    // 后继节点引用
    volatile Node next;
    
    // 当前节点关联的线程
    volatile Thread thread;
    
    // 条件队列中的后继节点
    // 在同步队列中，此字段用于指示节点的模式（SHARED或EXCLUSIVE）
    Node nextWaiter;
    
    /**
     * 空构造函数，用于创建头节点或模式标记
     */
    public Node() {
        // 头节点或模式标记使用此构造函数
    }
    
    /**
     * 构造函数，创建带有线程和模式的节点
     * @param thread 当前节点关联的线程
     * @param mode 节点模式（SHARED或EXCLUSIVE）
     * @param waitStatus 初始等待状态
     */
    private Node(Thread thread, Node mode, int waitStatus) {
        this.thread = thread;
        this.nextWaiter = mode;
        this.waitStatus = waitStatus;
    }
    
    /**
     * 构造函数，创建同步队列中的节点
     * @param thread 当前节点关联的线程
     * @param mode 节点模式（SHARED或EXCLUSIVE）
     */
    public Node(Thread thread, Node mode) {
        this(thread, mode, 0); // 同步队列节点初始状态为0
    }
    
    /**
     * 构造函数，创建条件队列中的节点
     * @param thread 当前节点关联的线程
     */
    public Node(Thread thread) {
        this(thread, null, CONDITION); // 条件队列中的节点初始状态为CONDITION
    }
    
    /**
     * 判断节点是否是共享模式
     * @return 如果是共享模式返回true，否则返回false
     */
    public final boolean isShared() {
        return nextWaiter == SHARED;
    }
    
    /**
     * 获取当前节点的前驱节点
     * @return 前驱节点
     * @throws NullPointerException 如果前驱节点为null
     */
    public final Node predecessor() throws NullPointerException {
        Node p = prev;
        if (p == null) {
            throw new NullPointerException("节点的前驱节点为null");
        } else {
            return p;
        }
    }
    
    /**
     * 设置节点的等待状态
     * @param newStatus 新的等待状态
     */
    public void setWaitStatus(int newStatus) {
        this.waitStatus = newStatus;
    }
    
    /**
     * 原子更新节点的等待状态
     * @param expect 期望的当前状态
     * @param update 要更新的新状态
     * @return 是否成功更新
     */
    public boolean compareAndSetWaitStatus(int expect, int update) {
        return WAIT_STATUS_UPDATER.compareAndSet(this, expect, update);
    }
    
    /**
     * 原子地将节点状态设置为SIGNAL
     * @return 是否成功设置
     */
    public boolean compareAndSetSignal(int expect) {
        return compareAndSetWaitStatus(expect, SIGNAL);
    }
    
    /**
     * 原子地将节点状态设置为CANCELLED
     * @return 是否成功设置
     */
    public boolean compareAndSetCancelled(int expect) {
        return compareAndSetWaitStatus(expect, CANCELLED);
    }
    
    /**
     * 原子地将节点状态设置为PROPAGATE
     * @return 是否成功设置
     */
    public boolean compareAndSetPropagate(int expect) {
        return compareAndSetWaitStatus(expect, PROPAGATE);
    }
    
    /**
     * 获取节点的等待状态
     * @return 当前等待状态
     */
    public int getWaitStatus() {
        return waitStatus;
    }
    
    /**
     * 设置节点的前驱节点
     * @param prev 前驱节点
     */
    public void setPrev(Node prev) {
        this.prev = prev;
    }
    
    /**
     * 获取节点的前驱节点
     * @return 前驱节点
     */
    public Node getPrev() {
        return prev;
    }
    
    /**
     * 设置节点的后继节点
     * @param next 后继节点
     */
    public void setNext(Node next) {
        this.next = next;
    }
    
    /**
     * 获取节点的后继节点
     * @return 后继节点
     */
    public Node getNext() {
        return next;
    }
    
    /**
     * 设置节点关联的线程
     * @param thread 关联的线程
     */
    public void setThread(Thread thread) {
        this.thread = thread;
    }
    
    /**
     * 获取节点关联的线程
     * @return 关联的线程
     */
    public Thread getThread() {
        return thread;
    }
    
    /**
     * 设置条件队列中的后继节点
     * @param nextWaiter 条件队列中的后继节点
     */
    public void setNextWaiter(Node nextWaiter) {
        this.nextWaiter = nextWaiter;
    }
    
    /**
     * 获取条件队列中的后继节点
     * @return 条件队列中的后继节点
     */
    public Node getNextWaiter() {
        return nextWaiter;
    }
    
    /**
     * 原子更新节点的后继节点
     * @param expect 期望的当前后继节点
     * @param update 要更新的新后继节点
     * @return 是否成功更新
     */
    public boolean compareAndSetNext(Node expect, Node update) {
        return NEXT_UPDATER.compareAndSet(this, expect, update);
    }
    
    /**
     * 判断节点是否已取消
     * @return 如果节点状态为CANCELLED返回true，否则返回false
     */
    public boolean isCancelled() {
        return waitStatus == CANCELLED;
    }
    
    /**
     * 判断节点是否需要被唤醒
     * @return 如果节点状态为SIGNAL返回true，否则返回false
     */
    public boolean isSignal() {
        return waitStatus == SIGNAL;
    }
    
    /**
     * 判断节点是否在条件队列中
     * @return 如果节点状态为CONDITION返回true，否则返回false
     */
    public boolean isCondition() {
        return waitStatus == CONDITION;
    }
    
    /**
     * 判断节点是否需要传播共享状态
     * @return 如果节点状态为PROPAGATE返回true，否则返回false
     */
    public boolean isPropagate() {
        return waitStatus == PROPAGATE;
    }
    
    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("Node{thread=");
        if (thread != null) {
            builder.append(thread.getName()).append('(').append(thread.getId()).append(')');
        } else {
            builder.append("null");
        }
        builder.append(", status=");
        switch (waitStatus) {
            case CANCELLED: builder.append("CANCELLED"); break;
            case SIGNAL: builder.append("SIGNAL"); break;
            case CONDITION: builder.append("CONDITION"); break;
            case PROPAGATE: builder.append("PROPAGATE"); break;
            default: builder.append(waitStatus);
        }
        builder.append(", mode=");
        if (nextWaiter == SHARED) {
            builder.append("SHARED");
        } else if (nextWaiter == EXCLUSIVE) {
            builder.append("EXCLUSIVE");
        } else {
            builder.append("UNKNOWN");
        }
        builder.append('}');
        return builder.toString();
    }
}